package net.jgrm.common.util;

import java.util.ArrayList;
import java.util.List;

/**
 * 通用分页对象
 * 与具体ORM实现无关的分页参数及查询结果封装
 * 注意所有序号从1开始
 *
 * @param <T> Page中记录的类型
 * @author service-common
 */
public class Page<T> {

    // 公共变量
    public static final String ASC = "asc";
    public static final String DESC = "desc";

    // 分页参数
    protected int pageNo = 1;
    protected int pageSize = 15;
    protected String orderBy = null;
    protected Order order = Order.ASC;

    // 返回结果
    protected List<T> result = new ArrayList<>();
    protected long totalCount = -1;

    /**
     * 默认构造函数
     */
    public Page() {
    }

    /**
     * 构造函数
     *
     * @param pageNo 页码
     */
    public Page(int pageNo) {
        this.pageNo = pageNo;
    }

    /**
     * 构造函数
     *
     * @param pageNo   页码
     * @param pageSize 每页大小
     */
    public Page(int pageNo, int pageSize) {
        this.pageNo = pageNo;
        this.pageSize = pageSize;
    }

    /**
     * 构造函数
     *
     * @param pageNo   页码
     * @param pageSize 每页大小
     * @param orderBy  排序字段
     * @param order    排序方向
     */
    public Page(int pageNo, int pageSize, String orderBy, Order order) {
        this.pageNo = pageNo;
        this.pageSize = pageSize;
        this.orderBy = orderBy;
        this.order = order;
    }

    /**
     * 获得当前页的页号，序号从1开始，默认为1
     *
     * @return 页号
     */
    public int getPageNo() {
        return pageNo;
    }

    /**
     * 设置当前页的页号，序号从1开始，低于1时自动调整为1
     *
     * @param pageNo 页号
     */
    public void setPageNo(final int pageNo) {
        this.pageNo = pageNo;
        if (pageNo < 1) {
            this.pageNo = 1;
        }
    }

    /**
     * 返回Page对象自身的setPageNo函数，可用于连续设置
     *
     * @param thePageNo 页号
     * @return Page对象
     */
    public Page<T> pageNo(final int thePageNo) {
        setPageNo(thePageNo);
        return this;
    }

    /**
     * 获得每页的记录数量，默认为15
     *
     * @return 每页记录数
     */
    public int getPageSize() {
        return pageSize;
    }

    /**
     * 设置每页的记录数量
     *
     * @param pageSize 每页记录数
     */
    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    /**
     * 根据pageNo和pageSize计算当前页第一条记录在总结果集中的位置，序号从1开始
     *
     * @return 第一条记录位置
     */
    public int getFirst() {
        return ((pageNo - 1) * pageSize) + 1;
    }

    /**
     * 计算偏移量（从0开始）
     *
     * @return 偏移量
     */
    public int getOffset() {
        return (pageNo - 1) * pageSize;
    }

    /**
     * 获得页内的记录列表
     *
     * @return 记录列表
     */
    public List<T> getResult() {
        return result;
    }

    /**
     * 设置页内的记录列表
     *
     * @param result 记录列表
     */
    public void setResult(final List<T> result) {
        this.result = result;
    }

    /**
     * 获得总记录数，默认值为-1
     *
     * @return 总记录数
     */
    public long getTotalCount() {
        return totalCount;
    }

    /**
     * 设置总记录数
     *
     * @param totalCount 总记录数
     */
    public void setTotalCount(final long totalCount) {
        this.totalCount = totalCount;
    }

    /**
     * 根据pageSize与totalCount计算总页数，默认值为-1
     *
     * @return 总页数
     */
    public long getTotalPages() {
        if (totalCount < 0) {
            return -1;
        }

        long count = totalCount / pageSize;
        if (totalCount % pageSize > 0) {
            count++;
        }
        return count;
    }

    /**
     * 是否还有下一页
     *
     * @return true:有下一页 false:没有下一页
     */
    public boolean isHasNext() {
        return (pageNo + 1 <= getTotalPages());
    }

    /**
     * 取得下页的页号，序号从1开始
     * 当前页为尾页时仍返回尾页序号
     *
     * @return 下一页页号
     */
    public int getNextPage() {
        if (isHasNext()) {
            return pageNo + 1;
        } else {
            return pageNo;
        }
    }

    /**
     * 是否还有上一页
     *
     * @return true:有上一页 false:没有上一页
     */
    public boolean isHasPre() {
        return (pageNo - 1 >= 1);
    }

    /**
     * 取得上页的页号，序号从1开始
     * 当前页为首页时返回首页序号
     *
     * @return 上一页页号
     */
    public int getPrePage() {
        if (isHasPre()) {
            return pageNo - 1;
        } else {
            return pageNo;
        }
    }

    /**
     * 获取排序字段
     *
     * @return 排序字段
     */
    public String getOrderBy() {
        return orderBy;
    }

    /**
     * 设置排序字段
     *
     * @param orderBy 排序字段
     */
    public void setOrderBy(String orderBy) {
        this.orderBy = orderBy;
    }

    /**
     * 获取排序方向
     *
     * @return 排序方向
     */
    public Order getOrder() {
        return order;
    }

    /**
     * 设置排序方向
     *
     * @param order 排序方向
     */
    public void setOrder(Order order) {
        this.order = order;
    }

    @Override
    public String toString() {
        return "Page{" +
                "pageNo=" + pageNo +
                ", pageSize=" + pageSize +
                ", orderBy='" + orderBy + '\'' +
                ", order=" + order +
                ", totalCount=" + totalCount +
                ", totalPages=" + getTotalPages() +
                '}';
    }
}